/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package principal;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.HeadlessException;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

/**
 *
 * @author
 * Abad Carmona, Pablo
 * Belesbia Rojas, Francy
 * Daneri Beltrán, Stephany
 */

/*INTERFAZ GRÁFICA DEL JUEGO*/
public class ConstelacionesGUI extends javax.swing.JFrame implements KeyListener, MouseListener {
    
    //DECLARACIÓN DE VARIABLES
    
    //El lienzo me permite insertar gráficos 2d, y usar métodos necesarios para 
    //graficación y validación 
    ConstelacionesLienzo lienzo;
    ConstelacionesLogica logica;
    
    //Estado de la arista, existen 2: 
    //0 antes de seleccionar el primer punto de esta y
    //1 antes de seleccionar el segundo punto
    int estadoArista; 
        
    public static final int BLANCA=0; //Constante de clase para las constelaciones blancas
    public static final int OSCURA=1; //Constante de clase para las constelaciones oscuras
    public int turno;                 //turno actual
    
    //Variable auxiliar que guarda: El primer punto de una arista a insertarse,   
    
    //puntoInicial y puntoFinal son variables auxiliares que guardan
    //la 1era coordenada de la nueva arista a ser insertada, 
    //están definidos cada uno como un vector de 3 componentes (x,y,estado)
    //donde el estado es si es punto inicial o final de una constelación
    Integer [] puntoInicial;          //el valor del estado es cero si el punto inicial coincide con el inicio de la constelacion         
    Integer [] puntoFinal;            //el valor del estado es irrelevante puesto que este corresponde al punto que cruzo con una arista
    Integer [] puntoTempObj;          //Punto temporal que pertenece a la constelación antes de marcar un objetivo
    
    ArrayList<Integer> estrellasTemporales; 
    boolean marcar;
    boolean marcar2;
    IA ia = new IA(3);
    ConstelacionesJugada cj = new ConstelacionesJugada();
    
    /**
     * Creates new form ConstelacionesGUI
     */
    //--------------------------------OJO: ESTA PARTE PUEDE SER ELIMINADA O PODRIAMOS AGREGAR ALGO--------------------------------------
    //HILO DE PRUEBA -- para posiblemente hacer precalculos, cronometros
    class PruebaThread implements Runnable{
        boolean parar=false;    
        
        Thread contador;
        
        public void iniciar(){
            contador = new Thread(this);
            contador.start();
            System.out.println("iniciado");
        }
        
        @Override
        public void run() {
            int cont=0;
            
            while(!parar){
                try {
                    contador.sleep(1000);
                } catch (InterruptedException ex) {
                    Logger.getLogger(ConstelacionesGUI.class.getName()).log(Level.SEVERE, null, ex);
                }
                System.out.println("Contador en: " +cont);
                cont++;
            }           
        }
        
    }
    //FIN DE HILO DE PRUEBA    
    //-----------------------------FIN DE OJO: ESTA PARTE PUEDE SER ELIMINADA O PODRIAMOS AGREGAR ALGO-----------------------------------
    
    //CONSTRUCTOR
    public ConstelacionesGUI() {
        estadoArista=0;                                      //porque no se ha seleccionado el primer valor de la arista
        turno=BLANCA;                                        //por nuestra definición de juego, inician las blancas
        initComponents();        
        logica = new ConstelacionesLogica();
        lienzo = new ConstelacionesLienzo(logica);
        logica.estado.turno = BLANCA;
        tableroJuego.setLayout(new BorderLayout());
        tableroJuego.add(lienzo);
        tableroJuego.setBackground(new Color(64, 67, 191));  //Color del universo en formato (R,G,B)
        setTitle("Constelaciones multiplayer");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        setResizable(false);
        pack();
        setLocationRelativeTo(null);   
        lienzo.addMouseListener(this); 
        
        init();                                             //llamada a postconstructor
    }
    
    public void init(){                                     //postconstructor para inicializar y reinicializar el juego
                                                            //sin salir de este
        logica.estado.nodos.clear();  
        logica.limpiarSegmentos();
        
        //Inserta las 25 estrellas al juego
        for (int i = 1; i <= 25; i++) {
            //Puesto que hay casos donde no puede insertar por
            //restricciones dadas (separación de 40px entre estrella y estrella)
            //se continúa insertando la estrella n-ésima hasta cumplir con la condición
            while(!logica.insertarNodo((int)(280*Math.random()+60),(int)(280*Math.random()+60),i));
        }
        
        lienzo.repaint();                                   //Dibuja el lienzo
        turno=BLANCA;                                       //como el juego vuelve a iniciar, el turno es del jugador blanco        
        logica.estado.turno = BLANCA;
        lblInstruccionyTurno.setText("Turno de las blancas");        
        logica.estado.objetivoO[0]=-1;
        logica.estado.objetivoO[1]=-1;
        logica.estado.objetivoB[0]=-1;
        logica.estado.objetivoB[1]=-1;
        marcar=false;
        marcar2=false;
        ////System.out.println(lienzo.nodos.size());        
    }
    
    @Override
    public void mouseClicked(MouseEvent e) {
        
           
        if(marcar){            
            
            puntoTempObj=logica.perteneceConstelacion(e.getX(),e.getY());            
            if(puntoTempObj[0]!=-1){
                //Metodo a ser usado por la maquina)
                //logica.marcarObjetivo(ptoTemp[0], ptoTemp[1], turno);
                marcar=false;
                marcar2=true;
                lblInstruccionyTurno.setText("Seleccione objetivo");
                lienzo.repaint();
            }
            return;
        }
        if(marcar2){
            Integer [] ptoTemp;
            ptoTemp=logica.esEstrella(e.getX(),e.getY());            
            if(ptoTemp[0]!=-1){
                logica.marcarObjetivo(puntoTempObj[0],puntoTempObj[1],ptoTemp[0], ptoTemp[1], turno);
                lblInstruccionyTurno.setText(turno==BLANCA?"Turno de las blancas":"Turno de las oscuras");
                marcar2=false;
                lienzo.repaint();
            }           
            return;
        }
        int turno1 = cj.jugarObjetivo(logica, estrellasTemporales);
        if(turno1!=-1){
            lblInstruccionyTurno.setText(turno==OSCURA? "Turno de las blancas":"Turno de las oscuras"); 
            turno = turno1;
            lienzo.repaint();  
            return;
        }     
                       
        if(estadoArista==0){                                //Cuando es el primer punto seleccionado de una arista a insertar
            estrellasTemporales = new ArrayList<>();
            //Caso inicial (para las blancas y las oscuras) - primer juego de blancas y oscuras
            if(logica.contar(logica.estado.segmentos)<2){ 
                Integer [] ptoTemp;
                
                //Evalúa si el primer punto de la constelación blanca u oscura (primera arista a insertar) es una estrella
                ptoTemp=logica.esEstrella(e.getX(),e.getY()); 
                
                //Si es una estrella 
                if(ptoTemp[0]!=-1){
                    estrellasTemporales.add(ptoTemp[0]);
                    estrellasTemporales.add(ptoTemp[1]);
                    estadoArista=1; //Cambia el estado para que en el siguiente evento utilice el segundo punto de la arista
                    lblInstruccionyTurno.setText("Seleccione el nodo final");
                    puntoInicial=ptoTemp;
                }
            }
            //Caso cuando no es inicial (para las blancas y las oscuras) - n-ésimo juego de blancas y oscuras
            else { 
                puntoInicial = new Integer[3];
                
                //evalúa si el punto corresponde a uno de los extremos de la constelacion
                puntoInicial=logica.perteneceConstelacion(e.getX(),e.getY()); 
                
                //Si es uno de los 2 extremos
                if(puntoInicial[0]!=-1){
                    //Cambia el estado para que en el siguiente evento utilice el segundo punto de la arista
                    estadoArista=1; 
                    lblInstruccionyTurno.setText("Seleccione el nodo final");                        
                }
            }
        }    
        else if(estadoArista==1){                           //Cuando es el punto final de la arista a insertar
            
            //Comprueba que nuestro segundo punto necesariamente sea una estrella
            puntoFinal=logica.esEstrella(e.getX(),e.getY()); 
            if(logica.distancia(puntoInicial[0], puntoInicial[1], puntoFinal[0], puntoFinal[1])>75) return;
            //Caso inicial (para las blancas y las oscuras) - primer juego de blancas y oscuras
            if(logica.contar(logica.estado.segmentos)<2){
                //El punto final debe ser una estrella y debe ser diferente del punto inicial
                if(puntoFinal[0]!=-1 && !(puntoInicial[0]==puntoFinal[0] && puntoInicial[1]==puntoFinal[1]) ){
                    estrellasTemporales.add(puntoFinal[0]);
                    estrellasTemporales.add(puntoFinal[1]);
                    //Permite que nuevamente se vuelva a seleccionar un punto inicial para una nueva arista
                    estadoArista=0; 

                    if(logica.insertarArista(puntoInicial[0],puntoInicial[1],puntoFinal[0],puntoFinal[1],turno,0,estrellasTemporales)){
                        System.out.println("Arista insertada");
                        for(Nodo n: logica.estado.nodos){
                            if(n.x==puntoInicial[0] && n.y==puntoInicial[1]){
                                n.perteneceAConstelacion=true; continue;                               
                            }
                            if(n.x==puntoFinal[0] && n.y==puntoFinal[1]){
                                n.perteneceAConstelacion=true;                               
                            }
                        }
                        if(turno==BLANCA) {
                            turno=OSCURA;
                            logica.estado.turno = OSCURA;
                        }
                        else {
                            turno = BLANCA;
                            logica.estado.turno = BLANCA;
                        }
                        lienzo.repaint();                                       //actualiza tablero
                        
                    }
                    else{
                        System.out.println("Error insertando Arista");
                    }
                    lblInstruccionyTurno.setText(turno==BLANCA?"Turno de las blancas":"Turno de las oscuras");
                }
            }
            //Caso no inicial (para las blancas y las oscuras) - juego n-esimo de blancas y oscuras
            else if (logica.contar(logica.estado.segmentos)< 10){
                //Si el nodo no es estrella y el nodo inicial no es igual al final
                if(puntoFinal[0]!=-1 && !(puntoInicial[0]==puntoFinal[0] && puntoInicial[1]==puntoFinal[1])){ 
                    estadoArista=0; //Ahora se requiere indicar un punto inicial para la arista                      
                    estrellasTemporales.add(puntoFinal[0]);
                    estrellasTemporales.add(puntoFinal[1]);
                    //Si el punto inicial de la arista a insertar coincide con el punto final de la constelacion
                    if(puntoInicial[2]==1){
                        if(logica.insertarArista(puntoInicial[0], puntoInicial[1], puntoFinal[0],puntoFinal[1], turno,1,estrellasTemporales)){ //inserta al final
                            System.out.println("Arista insertada al final");
                            for(Nodo n: logica.estado.nodos){                                
                                if(n.x==puntoFinal[0] && n.y==puntoFinal[1]){
                                    n.perteneceAConstelacion=true;                               
                                }
                            }   
                            if(turno==BLANCA){
                                turno=OSCURA;
                                logica.estado.turno = OSCURA;
                            } 
                            else {
                                turno = BLANCA;
                                logica.estado.turno = BLANCA;
                            }
                            lienzo.repaint();   
                        }
                        else{
                            System.out.println("Error insertando Arista");
                        }
                        lblInstruccionyTurno.setText(turno==BLANCA?"Turno de las blancas":"Turno de las oscuras");
                    }
                    //Si el punto inicial de la arista a insertar coincide con el punto inicial de la constelacion
                    else{
                        //Arista b=new Arista(x1,y1,x1+(int)(75 * ((x2-x1)/distancia(x1,y1,x2,y2)) ),y1+(int)(75 * ((y2-y1)/distancia(x1,y1,x2,y2)) ));
                        int pfx,pfy;
                        pfx=puntoInicial[0]+(int)(75 *((puntoFinal[0]-puntoInicial[0])/logica.distancia(puntoInicial[0],puntoInicial[1],puntoFinal[0],puntoFinal[1])));
                        pfy=puntoInicial[1]+(int)(75 *((puntoFinal[1]-puntoInicial[1])/logica.distancia(puntoInicial[0],puntoInicial[1],puntoFinal[0],puntoFinal[1])));
                        if(logica.insertarArista(pfx,pfy, puntoInicial[0],puntoInicial[1], turno,0,estrellasTemporales)){ //inserta al inicio
                            System.out.println("Arista insertada al inicio");
                            for(Nodo n: logica.estado.nodos){                                
                                if(n.x==puntoFinal[0] && n.y==puntoFinal[1]){
                                    n.perteneceAConstelacion=true;                               
                                }
                            }
                            if(turno==BLANCA){
                                turno=OSCURA;
                                logica.estado.turno = OSCURA;
                            }
                            else {
                                turno = BLANCA;
                                logica.estado.turno = BLANCA;
                            }
                                lienzo.repaint();   
                        }
                        else{
                            System.out.println("Error insertando Arista");

                        }
                        lblInstruccionyTurno.setText(turno==BLANCA?"Turno de las blancas":"Turno de las oscuras");
                    }
                } 
            }
            //Cuando ya se han usado los 10 palitos (aristas)
            else {
                               
                if(puntoFinal[0]!=-1 && !(puntoInicial[0]==puntoFinal[0] && puntoInicial[1]==puntoFinal[1])){ 
                    estadoArista=0; //Ahora se requiere indicar un punto inicial para la arista                      
                    estrellasTemporales.add(puntoFinal[0]);
                    estrellasTemporales.add(puntoFinal[1]);
                    //Si el punto inicial de la arista a insertar coincide con el punto final de la constelacion
                    if(puntoInicial[2]==1){
                        if(logica.insertarArista(puntoInicial[0], puntoInicial[1], puntoFinal[0],puntoFinal[1], turno,1,estrellasTemporales)){ //inserta al final
                            System.out.println("Arista insertada al final");
                            for(Nodo n: logica.estado.nodos){
                                if(n.x==puntoFinal[0] && n.y==puntoFinal[1]){
                                    n.perteneceAConstelacion=true;                               
                                }
                            }
                            if(turno==BLANCA){
                                turno=OSCURA;
                                logica.estado.turno = OSCURA;
                            } 
                            else {
                                turno = BLANCA;
                                logica.estado.turno = BLANCA;
                            }
                            lienzo.repaint();   
                        }
                        else{
                            System.out.println("Error insertando Arista");
                        }
                        lblInstruccionyTurno.setText(turno==BLANCA?"Turno de las blancas":"Turno de las oscuras");
                    }
                    //Si el punto inicial de la arista a insertar coincide con el punto inicial de la constelacion
                    else{
                        //Arista b=new Arista(x1,y1,x1+(int)(75 * ((x2-x1)/distancia(x1,y1,x2,y2)) ),y1+(int)(75 * ((y2-y1)/distancia(x1,y1,x2,y2)) ));
                        int pfx,pfy;
                        pfx=puntoInicial[0]+(int)(75 *((puntoFinal[0]-puntoInicial[0])/logica.distancia(puntoInicial[0],puntoInicial[1],puntoFinal[0],puntoFinal[1])));
                        pfy=puntoInicial[1]+(int)(75 *((puntoFinal[1]-puntoInicial[1])/logica.distancia(puntoInicial[0],puntoInicial[1],puntoFinal[0],puntoFinal[1])));
                        if(logica.insertarArista(pfx, pfy, puntoInicial[0],puntoInicial[1], turno,0,estrellasTemporales)){ //inserta al inicio
                            System.out.println("Arista insertada al inicio");
                            for(Nodo n: logica.estado.nodos){
                                if(n.x==puntoFinal[0] && n.y==puntoFinal[1]){
                                    n.perteneceAConstelacion=true;                               
                                }
                            }
                            if(turno==BLANCA){
                                turno=OSCURA;
                                logica.estado.turno = OSCURA;
                            }
                            else {
                                turno = BLANCA;
                                logica.estado.turno = BLANCA;
                            }
                                lienzo.repaint();   
                        }
                        else{
                            System.out.println("Error insertando Arista");

                        }
                        lblInstruccionyTurno.setText(turno==BLANCA?"Turno de las blancas":"Turno de las oscuras");
                    }
                }
                //Elimina estrella del vector
                
                //Inserta al inicio o final dependiendo el caso
            }
        }
        /*if(turno==OSCURA){
        //Juega la máquina
            ia.miniMax(logica.estado, 0);
            //ia.primeroMejor(logica.estado);
            logica.estado=ia.estadoJuego;
            turno=BLANCA;
            lienzo.repaint();
            lblInstruccionyTurno.setText(turno==BLANCA?"Turno de las blancas":"Turno de las oscuras");
            return;
        }*/
        if(logica.finJuego()!=-1){
            System.out.println("Ganaron las " + (logica.finJuego()==BLANCA?"Blancas":"Negras") );            
        }
        
    }
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        tableroJuego = new javax.swing.JPanel();
        lblInstruccionyTurno = new javax.swing.JLabel();
        btnReiniciar = new javax.swing.JToggleButton();
        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setPreferredSize(new java.awt.Dimension(500, 500));
        getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        tableroJuego.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));

        javax.swing.GroupLayout tableroJuegoLayout = new javax.swing.GroupLayout(tableroJuego);
        tableroJuego.setLayout(tableroJuegoLayout);
        tableroJuegoLayout.setHorizontalGroup(
            tableroJuegoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 500, Short.MAX_VALUE)
        );
        tableroJuegoLayout.setVerticalGroup(
            tableroJuegoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 500, Short.MAX_VALUE)
        );

        getContentPane().add(tableroJuego, new org.netbeans.lib.awtextra.AbsoluteConstraints(50, 60, -1, -1));
        getContentPane().add(lblInstruccionyTurno, new org.netbeans.lib.awtextra.AbsoluteConstraints(280, 20, 620, 30));

        btnReiniciar.setText("Reiniciar");
        btnReiniciar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnReiniciarActionPerformed(evt);
            }
        });
        getContentPane().add(btnReiniciar, new org.netbeans.lib.awtextra.AbsoluteConstraints(60, 30, 85, -1));

        jButton1.setText("Marcar Objetivo");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        getContentPane().add(jButton1, new org.netbeans.lib.awtextra.AbsoluteConstraints(150, 30, -1, -1));

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnReiniciarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnReiniciarActionPerformed
        init();
        
    }//GEN-LAST:event_btnReiniciarActionPerformed

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        lblInstruccionyTurno.setText("Seleccione el punto inicial");
        marcar=true;
    }//GEN-LAST:event_jButton1ActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(ConstelacionesGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(ConstelacionesGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(ConstelacionesGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ConstelacionesGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ConstelacionesGUI().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JToggleButton btnReiniciar;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel lblInstruccionyTurno;
    private javax.swing.JPanel tableroJuego;
    // End of variables declaration//GEN-END:variables

    @Override
    public void keyTyped(KeyEvent e) {
        JOptionPane.showMessageDialog(null, "Click");
    }

    @Override
    public void keyPressed(KeyEvent e) {
        
    }

    @Override
    public void keyReleased(KeyEvent e) {
        
    }

    
    @Override
    public void mousePressed(MouseEvent e) {
        
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        
    }
    
    @Override
    public void mouseEntered(MouseEvent e) {
        
    }
    
    @Override
    public void mouseExited(MouseEvent e) {
        
    }
}
